package demo03;

public class Demo03Synchronized {
    public static void main(String[] args) {
        Runnable sellTicket = new Runnable() { // 布置线程任务：售100张票
            private int ticket = 100; // 票总数100张

            @Override
            public void run() { // 每个线程开始任务的起点
                while (true) { // 无限循环，窗口一直开放
                    sell(); // 调用同步方法
                }
            }

            /*
             *  将判断是否售票与售票的语句块整合到同步方法中
             *  同步锁：
             *      如果非静态static方法，则为this（方法的调用者new Runnable()，即本例中的Runnable类对象sellTicket）
             *      如果是静态static方法，则为方法所在类的class文件对象（运用了反射概念），匿名内部类不能使用静态成员，因此不做演示
             *  第一个抢到优先权的线程抢到同步锁，进入同步方法执行语句，其他线程只能在外面等着
             *  线程在同步方法执行完毕后，重新上锁，并将锁继续给优先权高的线程，执行里面的语句
             *  如此往复，同步方法内的代码就只会有一条线程在执行，防止了线程安全问题
             */
            public synchronized void sell() {
                if (ticket > 0) { // 票数大于0，代表有票可售，进行售票
                    try { // 模拟出票时间
                        Thread.sleep(50);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "正在卖：" + ticket--); // 售1张票
                }
            }
        };

        // 开启三个线程：三个窗口
        new Thread(sellTicket, "窗口1").start();
        new Thread(sellTicket, "窗口2").start();
        new Thread(sellTicket, "窗口3").start();

        /*
         *  输出结果：各个窗口交替输出，输出的内容按顺序从100~1
         */
    }
}
